package middleware

import (
	"booking/models"
	"bytes"
	"context"
	"crypto/sha256"
	"encoding/hex"
	"io"
	"net/http"
	"sort"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
)

// PreventDuplicatePostRedisMiddleware 限制重复 POST 请求（基于 IP + Header + Body）
func PreventDuplicatePostRedisMiddleware(expire time.Duration) gin.HandlerFunc {
	return func(c *gin.Context) {
		if c.Request.Method != http.MethodPost {
			c.Next()
			return
		}

		// 获取客户端 IP
		clientIP := c.ClientIP()

		// 读取 Body 内容（读取后还原，供后续处理）
		bodyBytes, err := io.ReadAll(c.Request.Body)
		if err != nil {
			c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
				"message": "读取请求体失败",
			})
			return
		}
		c.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))

		// 获取 header 所有键值对（拼成稳定字符串）
		var headers []string
		for k, v := range c.Request.Header {
			// 忽略大小写，拼接为 Key:Value1,Value2
			headers = append(headers, k+":"+strings.Join(v, ","))
		}
		sort.Strings(headers) // 保证顺序一致
		headerString := strings.Join(headers, "|")

		// 构造 hash key: IP + header + body
		keyRaw := clientIP + "|" + headerString + "|" + string(bodyBytes)
		hash := sha256.Sum256([]byte(keyRaw))
		cacheKey := "repeat_post:" + hex.EncodeToString(hash[:])

		// 使用 Redis 设置唯一 key（NX = 不存在时才设置，避免重复）
		ctx := context.Background()
		ok, err := models.RedisClient.SetNX(ctx, cacheKey, "1", expire).Result()
		if err != nil {
			// Redis 错误，不能判断是否重复，允许继续请求（或按需调整为拦截）
			c.Next()
			return
		}
		if !ok {
			// Key 已存在，说明重复请求
			c.AbortWithStatusJSON(http.StatusTooManyRequests, gin.H{
				"code":    429,
				"message": "请勿重复提交请求",
			})
			return
		}

		c.Next()
	}
}
